package dao

import (
	"context"
	"errors"
	"github.com/qiniu/qmgo"
	"github.com/sirupsen/logrus"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/mongo"
	"monoblog/config"
	"monoblog/domain/model"
	"monoblog/util"
	"sync"
)

var (
	sectionRepo *SectionRepository // 单例实例存储变量
	once7       sync.Once          // 确保初始化只执行一次的同步工具
)

// 初始化 QMGO 集合（单例模式）
func NewSectionRepository() *SectionRepository {
	once7.Do(func() { // 并发安全的初始化逻辑，只会执行一次
		sectionRepo = &SectionRepository{
			collection: config.GetDataBase().Collection(model.SectionCollectionName), //指定集合名称
			ctx:        context.Background(),
		}
	})
	return sectionRepo // 返回唯一实例
}

type SectionRepository struct {
	collection *qmgo.Collection // QMGO 集合对象（替代原生 mongo.Collection）
	ctx        context.Context  // 上下文（用于数据库操作超时控制）
}

func (impl *SectionRepository) Add(section *model.Section) error {
	r, err := impl.collection.InsertOne(impl.ctx, section)
	if oid, ok := r.InsertedID.(primitive.ObjectID); ok {
		section.ID = oid.Hex()
	}
	return err
}

// UpdateByID - 按 ID 更新专栏
func (impl *SectionRepository) UpdateByID(id string, section model.Section) error {
	keyId, _ := primitive.ObjectIDFromHex(id)

	update := util.ObjToUpdateMap(section)
	if len(update) == 0 {
		return nil
	}

	updateDoc := bson.M{"$set": update}

	// 修复：捕获 UpdateOne 返回的错误
	err := impl.collection.UpdateId(impl.ctx, keyId, updateDoc)
	if errors.Is(err, mongo.ErrNoDocuments) {
		logrus.Warnf("record not found. dont update. id: %v", id)
		return nil
	}
	return err // 正确返回更新操作的错误
}

// DeleteByID - 按 ID 删除专栏 (对应 MongoDB DeleteOne)
func (impl *SectionRepository) DeleteByID(id string) error {
	keyId, _ := primitive.ObjectIDFromHex(id)

	// 执行删除操作
	err := impl.collection.RemoveId(impl.ctx, keyId)
	if errors.Is(err, mongo.ErrNoDocuments) {
		logrus.Warnf("record not found. dont delete. id: %v", id)
		return nil
	}
	return err
}

// FindByID - 根据ID查询专栏
func (impl *SectionRepository) FindByID(id string) (*model.Section, error) {
	keyId, _ := primitive.ObjectIDFromHex(id)

	var section model.Section

	err := impl.collection.Find(impl.ctx, qmgo.M{"_id": keyId}).One(&section)

	if errors.Is(err, mongo.ErrNoDocuments) {
		logrus.Warnf("record not found. id: %v", id)
		return nil, errors.New("找不到数据, id: " + id)
	}
	return &section, err
}

// FindList - 按条件查询专栏列表
func (impl *SectionRepository) FindList() ([]*model.Section, int, error) {
	var sections = make([]*model.Section, 0)

	filter := bson.M{} // 构建查询条件：空条件

	err := impl.collection.Find(impl.ctx, filter).Sort("seq").All(&sections)
	return sections, len(sections), err
}

// FindListByUserId 查询用户下的专栏list
func (impl *SectionRepository) FindListByUserId(userId string) ([]*model.Section, int, error) {
	var sections = make([]*model.Section, 0)

	// 构建查询条件：根据userId查询
	filter := bson.M{"userId": userId}

	err := impl.collection.Find(impl.ctx, filter).Sort("seq").All(&sections)
	return sections, len(sections), err
}

// ExistsByName 根据名称查询专栏是否存在（因为专栏名称只在userId下是唯一的）
func (impl *SectionRepository) ExistsByName(ignoreID string, name string, userId string) (bool, error) {
	if name == "" {
		return false, nil
	}
	// 构建查询条件
	filter := bson.M{"name": name, "userId": userId}

	if ignoreID != "" {
		keyId, _ := primitive.ObjectIDFromHex(ignoreID)
		filter["_id"] = bson.M{"$ne": keyId}
	}

	n, err := impl.collection.Find(impl.ctx, filter).Count()
	return n > 0, err
}

// CountByUserId - 查询用户下的专栏数量
func (impl *SectionRepository) CountByUserId(userId string) (int, error) {
	// 构建查询条件：根据userId查询
	filter := bson.M{"userId": userId}

	n, err := impl.collection.Find(impl.ctx, filter).Count()
	return int(n), err
}
